package applet.forces;

import java.awt.Point;
import java.util.ArrayList;
import java.util.List;

/**
 * Creates a list of global forces
 * (gravity, viscosity, centermass, and wall forces).
 * Wall forces are kept track of through a list of
 * WallData (since there can be multiple walls on at
 * a time. Mass will use this class to update each mass (itself)
 * according to the global forces info.
 *
 * @author Jesse Starr and Guy Tracy
 *
 */
public class GlobalForce {
    private double myGravityMagnitude;
    private double myGravityDirection;
    private double myViscosityMagnitude;
    private double myCenterOfMassMagnitude;
    private double myCenterOfMassExponent;
    private Point myCenterOfMassPoint;

    private boolean gravity;
    private boolean viscosity;
    private boolean center;

    private List<WallData> myWallForces;

    /**
     * Creates a list of all info for all
     * global forces with default values.
     * Currently only gravity is has a default value.
     */
    public GlobalForce() {
        myGravityMagnitude = 1;
        myGravityDirection = 90;
        myViscosityMagnitude = 0.5;
        myCenterOfMassMagnitude = 100;
        myCenterOfMassExponent = 2;
        myCenterOfMassPoint = new Point(0, 0);
        myWallForces = new ArrayList<WallData>();
        gravity = false;
        viscosity = false;
        center = false;
    }

    /**
     * Sets direction of gravity.
     *
     * @param set the direction
     */
    public void setGDirection(double set) {
        myGravityDirection = set;
    }

    /**
     * Gets gravity's direction.
     * @return
     */
    public double getGDirection() {
        return myGravityDirection;
    }

    /**
     * Sets gravity's magnitude.
     *
     * @param set gravity's magnitude
     */
    public void setGMagnitude(double set) {
        myGravityMagnitude = set;
    }

    /**
     * Get gravity's magnitude.
     */
    public double getGMagnitude() {
        return myGravityMagnitude;
    }

    /**
     * Toggle gravity on/off.
     */
    public void toggleG() {
        if (!gravity) {
            gravity = true;
        }
        else {
            gravity = false;
        }
    }

    /**
     * Check if gravity is on/off.
     * @return
     */
    public boolean gravityCheck() {
        return gravity;
    }

    /**
     * Gets viscosity magnitude.
     * @return
     */
    public double getVMagnitude() {
        return myViscosityMagnitude;
    }

    /**
     * Sets viscosity magnitude.
     * @param set viscosity magnitude
     */
    public void setVMagnitude(double set) {
        myViscosityMagnitude = set;
    }

    /**
     * Toggle viscosity on/off.
     */
    public void toggleV() {
        if (!viscosity) {
            viscosity = true;
        }
        else {
            viscosity = false;
        }
    }

    /**
     * Checks if viscosity is on/off.
     * @return
     */
    public boolean viscosityCheck() {
        return viscosity;
    }

    /**
     * Gets centermass force magnitude.
     *
     * @return
     */
    public double getCOMMagnitude() {
        return myCenterOfMassMagnitude;
    }

    /**
     * Sets centermass force magnitude.
     *
     * @param set magnitude
     */
    public void setCOMMagnitude(double set) {
        myCenterOfMassMagnitude = set;
    }

    /**
     * Gets centermass force exponent.
     * @return
     */
    public double getCOMExponent() {
        return myCenterOfMassExponent;
    }

    /**
     * Sets centermass exponent.
     * @param set exponent
     */
    public void setCOMExponent(double set) {
        myCenterOfMassExponent = set;
    }

    /**
     * Get center of mass.
     * @return
     */
    public Point getCOMPoint() {
        return myCenterOfMassPoint;
    }

    /**
     * Set center of mass point.
     * @param x of COM point
     * @param y of COM point
     */
    public void setCOMPoint(int x, int y) {
        myCenterOfMassPoint.x = x;
        myCenterOfMassPoint.y = y;
    }

    /**
     * Toggle centermass force on/off.
     */
    public void toggleC() {
        if (!center) {
            center = true;
        }
        else {
            center = false;
        }
    }

    /**
     * Checks if centermass force is on/off.
     * @return
     */
    public boolean centerCheck() {
        return center;
    }

    /**
     * Adds data for wall repulsion forces.
     * If a new Wall Force is added for a wall,
     * but that wall already has a wall force,
     * remove the old force and replace it
     * with the new one. If the wall has no wall
     * force, then just add the new force.
     *
     * @param magnitude of force
     * @param exp of force
     * @param id of which wall
     */
    public void addWallData(double magnitude, double exp, int id) {
        WallData myNewWallForce = new WallData(magnitude, exp, id);

        for (WallData w : myWallForces) {
            if (w.getID() == myNewWallForce.getID()) {
                myWallForces.remove(w);
                myWallForces.add(myNewWallForce);
                return;
            }
        }

        myWallForces.add(myNewWallForce);
    }

    /**
     * Returns a list of the wall forces.
     *
     * @return
     */
    public List<WallData> getWallData() {
        return myWallForces;
    }

    /**
     * Toggle wall forces on/off.
     *
     * @param wall id
     */
    public void toggleW(int wall) {
        for (WallData w : myWallForces) {
            if (w.getID() == wall) {
                w.toggle();
                break;
            }
        }
    }

    /**
     * Checks if wall forces are on.
     * @param wall id
     */
    public boolean wallCheck(int wall) {
        for (WallData w : myWallForces) {
            if (w.getID() == wall && w.checkWall()) {
                return true;
            }
        }

        return false;
    }
}
